#include "functions.h"

void set_beta(){
  int i;
  double r;

  beta  = ( double * ) malloc( sizeof( double ) * number_of_layers );

  beta[ 0 ] = beta1;
  beta[ number_of_layers - 1 ] = betaL;

  r = pow( ( betaL / beta1 ), 1.0 / ( number_of_layers - 1 ) );

  for( i = 1; i < number_of_layers - 1; i++ )
    beta[ i ] = beta1 * pow( r, i );

  printf("------------\n");

  for( i = 0; i < number_of_layers; i++)
    printf( "%d : %f\n", i, beta[ i ] );

  printf("------------\n");

}

void update_model(){
  // ソートされていることが前提
  int i, j;
  double tmp;
  
  // Center
  // Layer 0
  for( j = 0; j < number_of_dimensions; j++ ){
    tmp = archive[ 0 ].individuals[ 0 ].design_variables[ j ] + archive[ 0 ].individuals[ 1 ].design_variables[ j ]
      - archive[ 0 ].individuals[ each_individuals * 2 - 1 ].design_variables[ j ];

    //layers[ 0 ].center[ j ] = ( 1 - alpha ) * layers[ 0 ].center[ j ] + alpha * tmp;
    layers[ 0 ].center[ j ] = ( 1 - beta[ 0 ] ) * layers[ 0 ].center[ j ] + beta[ 0 ] * tmp;

  }

  // Layer L - 1
  for( j = 0; j < number_of_dimensions; j++ ){
    tmp = archive[ number_of_layers - 1 ].individuals[ 0 ].design_variables[ j ]
      + archive[ number_of_layers - 1 ].individuals[ 1 ].design_variables[ j ]
      - archive[ number_of_layers - 1 ].individuals[ each_individuals * 2 - 1 ].design_variables[ j ];

    //layers[ number_of_layers - 1 ].center[ j ] = ( 1 - alpha ) * layers[ number_of_layers - 1 ].center[ j ] + alpha * tmp;
        layers[ number_of_layers - 1 ].center[ j ] = ( 1 - beta[ number_of_layers - 1 ] ) * layers[ number_of_layers - 1 ].center[ j ] + beta[ number_of_layers - 1 ] * tmp;
  }

  // Layer 1 to L - 2
  for( i = 1; i < number_of_layers - 1 ; i++ ){
    for( j = 0; j < number_of_dimensions; j++ ){

      tmp = archive[ i ].individuals[ 0 ].design_variables[ j ]	+ archive[ i ].individuals[ 1 ].design_variables[ j ]
	- archive[ i ].individuals[ each_individuals * 3 - 1 ].design_variables[ j ];

      //layers[ i ].center[ j ] = ( 1 - alpha ) * layers[ i ].center[ j ] + alpha * tmp;
      layers[ i ].center[ j ] = ( 1 - beta[ i ] ) * layers[ i ].center[ j ] + beta[ i ] * tmp;

    }
  }
  
  // Sigma
  for( i = 0; i < number_of_layers; i++ ){
    for( j = 0; j < number_of_dimensions; j++ ){
      tmp = sqrt( calc_indi_var( i , j ) );
      layers[ i ].sigma[ j ] = ( 1 - beta[ i ] ) * layers[ i ].sigma[ j ] + beta[ i ] * tmp;
      //      layers[ number_of_layers - 1 ].sigma[ j ] = ( upper_limit - lower_limit ) / 2;
    }
  }
}

// lは何番目のレイヤか？、dは何次元目か？
double calc_indi_var( const int l, const int d ){
  int i;
  double average = 0.0;
  double sum = 0.0;
  int num;

  if( l == 0 || l == number_of_layers - 1 )
    num = ( int ) ( each_individuals * 2 * K );
  else
    num = ( int ) ( each_individuals * 3 * K );

  for( i = 0; i < num; i++ ){
    average += archive[ l ].individuals[ i ].design_variables[ d ];
  }

  average = average / num;

  for( i = 0; i < num; i++ ){
    sum += pow( ( archive[ l ].individuals[ i ].design_variables[ d ] - average ), 2 );
  }

  return sum / num;
}

void set_init_center_sigma(){
  int i, j;

  // set sigma
  for( i = 0; i < number_of_layers; i++ )
    for( j = 0; j < number_of_dimensions; j++ )
      //      layers[ i ].sigma[ j ] = sqrt( pow( ( upper_limit - lower_limit ), 2 ) / 12 );
      layers[ i ].sigma[ j ] =  ( upper_limit - lower_limit ) / 2;

  // set center
  for( i = 0; i < number_of_layers; i++ )
    {
      population_sort( layers[ i ].individuals, each_individuals );

      for( j = 0; j < number_of_dimensions; j++ )
	layers[ i ].center[ j ] = layers[ i ].individuals[ 0 ].design_variables[ j ];
    }

}

void initialize_layers(){
  int i, j;

  layers = ( LAYER * ) malloc( sizeof( LAYER ) * number_of_layers );

  for( i = 0; i < number_of_layers; i++ )
    {
      layers[ i ].sigma  = ( double * ) malloc( sizeof( double ) * number_of_dimensions );
      layers[ i ].center = ( double * ) malloc( sizeof( double ) * number_of_dimensions );
      
      layers[ i ].individuals = ( INDIVIDUAL * ) malloc( sizeof( INDIVIDUAL ) * each_individuals );
      
      for( j = 0; j < each_individuals; j++ )
	{
	  layers[ i ].individuals[ j ].design_variables = ( double * ) malloc( sizeof( double ) * number_of_dimensions );
	}
    }

}
